home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Linux Cubed Series 8: LINUX Games
/
Linux Cubed Series 8 - LINUX Games.iso
/
games
/
x11
/
rpg
/
crossfir.000
/
crossfir
/
crossfire-0.92.4.client
/
Protocol
< prev
next >
Wrap
Internet Message Format
|
1996-04-21
|
47KB
From Eric Anderson:
Overall, the client talks to the server through a tcpsocket. It recieves
messages telling it what to do, and it sends inputs to the server. Many
of the commands are more low-level than would be preferrable, but the
low-level commands mesh better with the current crossfire implementation.
------------------------------------------------------------------------------
Since Mark's and Eric's client efforts were merged, there is no real
good documentation on how things are sent. For stuff I (Mark) have done,
I have included the workings immediately below. The previous protocol
file then follows.
C->S: reply <text>
Sends <text> as a reply to the last query command sent.
S->C: query <flags> <text>
Asks the client program for input. This is only used in a few places -
mostly in creating a character and login, but in fact anyplace in the server
that changes the input state (pl->contr->state, ST_*), should send a query.
<flags> are detailed in the <newclient.h> file, which is common to
both the client and server. The flags of relevance to this command
are the CS_QUERY flags.
The client is free to ignore the flags. However, if the server
just wants a single character as a reply, that is all it uses, even if
the client sends a long string (Server will use the first character.)
<txt> is the questoin/prompt that should be printed. Right now,
it is typically just a ':'. Client should display it no matter what
is is, however. An empty string (""), can be sent if there is no
question/prompt.
C->S: command <txt>
Client sends a command to the server. Ordinary commands (ie, north,
west, apply, maps, etc), might be sent, commands with options may be sent
(ie, 'invoke create food of booze', 'cast medium fireball'. There
are a few special commands that can also be sent.
'fire' command is a special case. The server will handle repeat
firing.
'fire_stop' will be sent to inform the server to stop firing. A different
command name has been chosen to make things easier on the server
('fire_stop' should be a 0 time command, with the rest of the fire commands
actually taking some time.) In some cases, 'fire_stop' maybe sent almost
immediately after the first fire (in cases where the player only wants to
fire once).
------------------------------------------------------------------------------
NOTE - this is a long message. If you are totally uninterested in
the client/server project, just skip it.
I figured it would be a good idea to post the revised Protocol. I know
at least a few people have comments which I have put in. But first, I would
like to make a few comments/ask a few questions.
1) Server output buffer overflow: What to do in this situation has
not really be determined. Keeping the client on-line becomes difficult,
because the server can not be sure of the information that the client
did not get, and likewise, the client can not be sure of what information
it did not get. One solution would be to have something like a
RESEND_ALL_DATA command that the client sends to the server. (Server
would need to send some command to the client informing it of the
data loss in the first place.
AFter getting the RESEND_ALL_DATA, the server then sends all the player
information (stats, items) and the map information. (note that this will
take a nontrivial amount of time)
This works quite well, depending on what caused the overflow in the
first place. If it was just a temporary backlog, this is not a problem.
If the player is on a slow link, and went someplace where a lot of
updates is going on, this won't help much (but in such a case, the
player will probably die, which will then end the updates.
Other option is drop the connection (as if the player dropped it.) What
happens in this case has not been determined. Saving the player where
he was is a bad idea for 2 reasons: 1) He may now be trapped (behind
a gate, with the lever on the other side), or 2) He may be in a treasure
chamber. Picks everything up, breaks the connection (and is thus
saved with all his good stuff), reconnects sometime later (when the map
has reset), and repeats the process. At some point, he then
exits.
One option, especially with NOT_PERMADEATH, would be to just 'kill'
that character, which pops him back to the starting town, and then
save him. A bit harsh, however.
What might be the best way is to have the configurable option of where the
player gets sent to (map and location) when the connection is lost.
One situation might be a jail cell, with a savebed, but otherwise no
way out. Thus, mail to the site administrator would need to be sent
2) Conversation between me and others have gone on about whether absolute
or relative coordinates should be used.
Relative has several advantages: You can not cheap (with absolute,
if you are at 0,0 (or the top of left row), you know that those walls could
not contain secret doors.) Teleporters are another problem - with
absolute, you would know where you were teleported to.
The disadvantage is that the client and server need to be synchronized
to where they think the player is. Ie, server things player is at 15,12
and gets an EXAMINE +2 -1 (which woudl be 17,11)
When client issued that command, it thought that the player was at 14,11
(and was thus examining 16,10). Only C->S commands have this problem,
S->C commands would not - the server would make sure it sends the
player movement first.
Absolute has some advantages/problems also:
EXAMINE problem above is not a problem.
Generating a random offset when the map is loaded that is then added
to all x and y locations would make it impossible to know if you are at
a top of left wall (this could be disabled.)
Absolute should probably be easier to debug.
Absolute does have a problem with the MOVE command for the player -
this is pretty much the same as the EXAMINE command that relative
has: The client would need to know where the player is to do
proper move commands (ie, player is at 12,10. Client does
a MOVE <tag> 13 10 (to move the player to space 13 10). Player types
north. Client still thinks player is at 12,10 (has received update
for it yet - perhaps never will if 13,10 was a wall). Do you send
MOVE 12 9 or MOE 13 9? With relative, it would be MOVE 0 -1 no matter
what.
So now, once again, I am leaning to using relative coordinates (player
movement is much more important than examing spaces.) But since previous
version suggested absolute coordinates were going to be used, I thought
it a good idea to bring this up, in case there are people who want to
give reasons in support of absolute coordinates.
3) ITEM vs MAP command: What gets sent as what has not been fully
determined. MAP may end up sending archetype or animation
sequences. In this case, it would be reasonable that ITEM commands
are only sent for items in the same square the player is on.
If MAP ends up using faces, then only animated items that are
continously animated (ie, diamonds, wands, etc, not grated, gates,
etc) would be sent with ITEM commands. But this might be extended to
include any item that the player picks up (so as the player moves around
the visible map, new ITEM commands need not be sent.
That is all for now - the Protocol file follows.
--Mark
------------------------------------------------------------------------------
Some of these commands have actually been implement, and are denoted
with (done) or other status in the area they are described.
Quick summary of Protcol commands:
Fields enclosed in < and > fields that are variable. [ and ] denote
optional fields, and these can be nested. { and } mean that the information
contained within these may be repeated many times, but with different values
C->S means client to server, S->C means server to client.
C->S: PROTOCOL <val> (informs server its protocol versions, also triggers
new client status. Completed)
C->S: SEND_IMAGE_NAMES (requests the server to send all the image names
it knows about. Optional startup command.
Completed)
S->C: I_IMAGE (list) (list of the image names. Exact format detailed
below. Completed)
C->S: SEND_ARCH_NAMES (These two commands are sme as the IMAGE commands
S->C: I_ARCH (list) above, except send/request the archetype names.
Completed.)
C->S: LOGIN <version> <name> <password>
(Logs in a player - client side completed)
S->C: TEXT <message> (Sends text that the client should display. Completed)
S->C: PLAY <sound> <vol>
(Informs the client it should play a sound)
S->C: STAT <stat> <current> <maximum>
(Sends a player stat - Done)
C->S: REQUEST <name> <type>
(requests data. Done)
S->C: TRANSMIT <name> <type> <length>
(sends data. Done)
(both): ERROR [<type> [<name>]] <text>
Reports an error (Done)
S->C: QUERY <flags> <text>
Asks the client/player a question. (Done on
client side - on server side, input still needs
to be done)
S->C: KNOWN_SPELLS {<name>}
sends a list (string) of all the spells the player
knows.
S->C: RANGE <range> <tag>
Informs client that item <tag> is now range attack
<range>
C->S: APPLY <tag> <x> <y>
Applies an item.
C->S: FIRE <flags> <tag>
Fires an object/spell.
C->S: SAY <flags> <text>
Say something to other players/NPC's
C->S: REPLY <text> Response to a query command.
C->S: SET <var> <value>
Set some variable to value
C->S: EXAMINE <tag> <locx> <locy>
Look at object/space at <locx> <locy>
C->S: COMMAND <text> Have the server run some command (who, maps, etc)
C->S: SET <var> <val> Sets a variable to a specific value (what those
values mean vary from variable to variable)
S->C: ITEM <length_flags> <tag> <locx> <locy> <flags> <arch_name> <image_name>
<weight> <nrof> <name>
Sends a piece of ITEM information to the client.
Many of the values are optional - what values are
sent is determined by the <length_flags> value.
S->C: VIEW <tag> Sets item with <tag> as the object that sees the map
S->C: MAP_END Tells the client that it has sent the full map
update for that particular 'tick'. Gives the
client some idea if it should update the
map display.
(both) MOVE <tag> <number_of> <from_x> <from_y> <to_x> <to_y>
Moves an item. In the client to server direction,
this could probably be handle by an ITEM command.
==============================================================================
>GENERALITIES
>============
>
>A bi-directional 8-bit wide clean error-free channel of some form
>exists between the client and the server. Absolutely all communication
>between them occurs on this channel and a client can receive everything
>it needs to run through it. Typically this channel will be a TCP/IP
>connection, but it may very well in some situations be a high speed
>modem connection or a UN*X pipe or some completely different network
>protocol. (DONE - code taken from old client program)
>
>In practice the up channel (from client to server) and the down channel
>(from server to client) function as two independent uni-directional
>chutes. If one side has something to tell to the other it just drops a
>packet into its send channel and forgets about it. Confirmations are
>not given or expected. The sender just assumes that the receiver will
>handle the packet or it will complain in another packet. At the same
>time the two chutes may be communicating about two entirely different
>subjects.
>
>Each packet consists out of one line of text terminated by a newline
>(0x0a) character. Line lengths of up to 4096 characters (including the
>terminating newline) are guaranteed to work. The receiver may
>correctly interpret longer packets, silently drop them or send an error
>message (see below) depending on what makes sense for the receiver.
>All characters are case sensitive.
>
>Every packet begins with a word terminated either by a space (0x20) or
>the end of the packet. The interpretation of the rest of the line
>depends on the initial word.
>
The output buffer on the server will be large enough to hold
several packets (right now, it is set for 32K). Non blocking i/o
is set on the socket, so data will disappear if the socket fills up.
All <flags> detailed in this file are in the newclient.h header
file. These are always sent in base 10 form (ie, 10 instead of 0xa)
For cases where a protocol command has several arguments, and some
of these are string's that may contain spaces, these arguments
should then be double quoted.
Example of a LOGIN command:
LOGIN "cfclient 1.0 (X11)" "Tiberius" "????"
All of these need to be double quoted - the client version may very
well have spaces (like this one does), and the name or password for
a character could also have spaces.
Note that the double quoting is not perfect. If the quoted string has a
double quote, then it may not get interperted properly. Example:
""hello"" there" would get interperted as two arguments, one "hello" and the
other would be there" There is no foolproof way to totally handle this.
Note that if the string is the last argument of a protocol command,
then double quoting is not needed. Examples are TEXT commands -
the remainder of the line is the text to be printed.
The base input routines in both the client and server are completed.
==============================================================================
STARTUP
=======
Note that the order of this section is the order that the commands
should be sent.
------------------------------------------------------------------------------
C->S: PROTOCOL (revision) This is the revision number that the client
understands. The server should be able to communicate to a client with any
protocol version: If the protocol is older than the servers, the server
will know what commands to not use.
In general, changes to the protocol should not happen very often, but this
gives a mechanism for making changes and not requiring every client to
upgrade. The old clients will just not be able to take advantage of the new
commands.
In cases where the client has a newer protocol than the server, there may
be problems, as the client will send commands to the server that the server
does not understand (possibly - depends what commands are added.) But this
situation should not happen very often, as the servers should in general be
kept up to date, and very seldom see a client newer than they are. One
solution to this is to have the client know all the commands that are added
to the protocol.
The PROTOCOL command has been implemented. In fact, it is the way the
client informs the server that it is a 'new' client. However, since
revision 1 of the protocol is not completed, no checking is done for
compatibility. The way it should be handled in the server is like this: In
functions that send the new protocol commands, it should check to make sure
the client would understand. If not, it should call whatever functions (or
do nothing) that get the same results with the older protocol requests.
These functions may in turn call functions that use even older protocol
requests. A function should never call a function that uses a newer
protocol command than what it uses. The way to implement this is to have 1
top level function of each command, with this function sending the
appropriate request.
------------------------------------------------------------------------------
C->S: SEND_IMAGE_NAMES
S->C: I_IMAGE (image) (image) ... - the I_ stands for initialization stage.
What the server does is send all the image names it knows about to the
client, so the client can see if it is missing any images. Any number
of image names can be on one line (within limit of 4096 bytes). (Done)
------------------------------------------------------------------------------
C->S: SEND_ARCH_NAMES
S->C: I_ARCH (archname) (archname) ... - this sends all the archetype
names the server knows about to the client. In this way, the client will
know if it is missing any archetypes.
The client can determine if it wants the I_ARCH and I_IMAGE stuff sent. The
idea is that if the client knows what is missing, it can get that information
at startup, instead of later when playing the game. The client can then do
REQUEST's to the server to get the information it needs.
The first name must be START, and the last be END. This makes the
client code quite a bit simpler.
Note - while these are meant for initialization stage only, the
SEND_* commands can be sent to the server at any time.
------------------------------------------------------------------------------
C->S:LOGIN <client-version> <name> <password>
Before play can actually begin, this command must be sent.
Other commands may have been sent before this (PROTOCOL must have
been, and various SET and SEND_IMAGE or SEND_ARCH names may also
have been sent.
<client-version> is a string created by the client at compile time. The
server should not treat different clients differently. This string is just
there to be able to gather statistics (and to correlate with ERROR packets).
<name> and <password> are is the player's name and password. It is
up to the client to input these, do keystroke hiding if desired, etc.
the client-version, name, and password all must be double quoted.
This is because any of those fields could contain spaces.
It is up the client to confirm if the player wants to LOGIN again
when he is already playing a character. When the server receives
this command, the current character is terminated - the server assumes
that this is what the player wants to do, and doesn't do confirmation
on its part)
==============================================================================
>VALID COMMANDS FROM THE SERVER TO THE CLIENT
>============================================
>MAP <locx1> <locy1> <image1> <locx2> <locy2> <image2> ...
>Using one of these commands the server may tell the client that it sees
>the map at a series of location given by coordinate pairs. The name
>refers to the image to use for the particular map location. If the
>client doesn't know that particular name, it asks the server for it
>(see REQUEST/TRANSMIT).
If the same location is received in one or a series of MAP commands,
this means that multiple objects are on that square.
------------------------------------------------------------------------------
>
>UNMAP <locx1> <locy1> <locx2> <locy2> ...
>This command tells the client that a certain series locations isn't any
>longer in the LOS of the player. The client may respond to this by
>erasing the squares in question, shading them to indicate to the user
>that they aren't any longer directly visible or just by doing nothing.
No matter what the client does, the data in unmapped squares is just
old data - it may very well not be correct.
------------------------------------------------------------------------------
S->C: REMAP <locx1> <locy1> <image1> ....
This is the same as the MAP command (including format), except it
means that the client should remove all contents on the square
sent. In this way, an UNMAP is not required. the blocked face
image can be sent for squares no longer visible.
How the server uses the MAP/UNMAP/REMAP commands is up to it.
------------------------------------------------------------------------------
ITEM <length_flags> <tag> <locx> <locy> <flags> <arch_name> <image_name>
<weight> <nrof> <name>
Sends item information to the client. ITEM is used for alive
objects and objects in the players inventory. In fact, MAP could be
used for all objects on the MAP except those below the player and
in the players inventory. How the server determines what is sent as
an ITEM and as a MAP command is up to it.
<length_flags> is a bitmask of what values it is sending along. Whether
the server actually uses this to any meaningful value, or just sends
along the entire ITEM each time is up to it.
The <length_flags> have the following meaning:
0x1 <flags>
0x2 <arch_name>
0x4 <image_name>
0x8 <weight>
0x10 <nrof>
0x20 <name>
Note that there is no entry for <tag> and location. These values
must always be sent.
The order of the data is always that of the full ITEM command. So
if <length_flags> was 0xA, then the format would be:
ITEM 10 <tag> <locx> <locy> <arch_name> <nrof>
Note that the <length_flags> is always converted into a base 10 form
when sending.
<tag> is a unique number for that object for the game. In this
way, both the client and server will always know that specific item
is being referred to.
<locx> and <locy> are the location of the object on the map.
If <locx> is IN, then <locy> is the tag that the item is contained
in.
<flags> contains various flags.
values from 0-8 are direction. 0 is no direction, 1 is north,
2 is north east, 3 is east, 4 is southeast, and so in the directions,
with 8 being northwest. These are the same that the server presently
uses all over the place, but (At least right now) seem to have
no enumeration/define setting this.
0x10 - this is the player object. Note the VIEW will not necessary
tell the client this, but the client needs to know what objects should
be the players for setting stats, etc.
0x20 - this is a container. This may not be truely necessary, but
gives the client an idea if this item is applied that things should
go in here.
0x40 - delete the item (ie, it is used up, destroyed, etc.)
0x80 - this is an update for the item. This may not be
used - the client should make sure on its own if it knows
an item with that tag. This should not be difficult - the
client isn't going to be keeping track of that many items, so
at worst, it could just look through its entire linked list.
<arch_name> is the archetype name. This gives the client enough
information to handle the animations. Also, the local client archetype
file may have more information on this item, so that the client can perform
intelligent actions on it.
<image_name> is the image name. This should rarely be sent - only in
cases where the image name is actually changed (things like gems of
great value, etc)
<weight> is the object weight. This should only be sent for items in the
look and inventory windows.
<nrof> is the number of objects.
<name> is the name of the object, with double quotes around it (so
if future options are added, it will be easier to parse for objects
that have spaces.) In general, it is up to the client to do special
things based upon names (like equipped, magic, etc.)
Note that color is not sent for any objects. Changing color in
objects is strongly discouraged - the only system that can use it
are fonts or bitmaps on color displays. XPM can not have their color
changed, no can you change the color on monochrome systems.
Notes:
I believe in some followup, both MAP and ITEM commands had (light_value)
as part of their description (if/when light sources get added). These
are not needed right now - the PROTOCOL revision can add this in later,
and still have things work. Since adding light seems like a long ways
away, and can easily be handled with <length_flags> for the ITEM
command (server always clear that flag, and thus never send light value
for old clients), it doesn't seem worthwhile to try and support it now.
Depending on the implementation of it, what exactly gets sent may
vary.
------------------------------------------------------------------------------
VIEW <number>
After this command the client considers the item with the tag <number>
to be the viewpoint item and will always try to center the map around
it. This is typically the item which is the player object.
This is not strictly needed since a flag in the ITEM command informs
the client what the player object is. But it is a very nice
extension - if a spell like magic eye, or perhaps find familiar is
added, it would allow the player/owner to look at the map through this
eye.
------------------------------------------------------------------------------
MOVE - same as the client command that is sent to the server.
------------------------------------------------------------------------------
Note that this example is grossly out of date on the format it uses
for many of the commands.
Examples of how the above works (taken from another mail message by Carl)
Server->Client: VIEW 123
(states that object 123 is the center object of the map, and calculates
LOS accordingly).
S->C: MAP 40 40 floor 41 40 wall 42 40 wall ...
(sets what objects are where. IT is not clear in the present
protocol about sending two different images with the same coordinate
via the map command. I would think that this means that there are those
two images there, and not that an overwrite should occur)
S->C: ITEM 123 44 44 1 Carlsimage Carl
^ ^ ^ ^ ^ ^
Itemtag ---| | | | | |
X coordinate ---| | | | |
Y coordinate ------| | | |
Quantity ------------| | |
Name of image ----------| |
Name of item ----------------------|
(this is the player item. The view command centers the map
around this object).
S->C: ITEM 433 IN 123 1 helmetimage X ray Helmet (worn)
Tells the client that this item is in the player item. It can
keep track of this in the inventory window. Note that the (worn)
is just part of the name. If the client recognizes this and then does
something special, that is its perogative.
More item commands like the above would happen as the players inventory
is sent. Now that you could having something like:
S->C: ITEM 600 IN 123 1 luggage The Luggage
S->C: ITEM 605 IN 600 5 gems Gems
The first states that the player is carrying the luggage, and the second
is stating that he has 5 gems in the luggage.
C->S: MOVE 123 44 45
A request by the client to move the player (object 123) south (from
44 to 45). Remember, that the maps make 0,0 as the upper left corner,
not lower left as in standard geometry.
The server then process this command. If the player can make this
move (no wall), and when sufficient time has passed (slowdown factor),
it sends:
S->C: ITEM 123 44 45
Telling the client that object 123 is now at 44,45. IT does not
need to send full data, since this object never left LOS.
However, this does require that the server keep track of an object in
LOS or if it leaves it. This because a bit of an implementation problem -
you don't want to keep track of whether each object is in LOS for
each player - this would chew up a lot of memory and would probably
hard code some maximum number of players (if you use an int, you only
have 32 bits for LOS for players).
As I see it, an array of some sort will need to be kept in the
player structure, with this array containing what objects/images were
last drawn around the player. Then each tick, you go through and see
what is around the player, and see if any new objects have appeared,
and send ITEM/MAP commands for them. A linked list could be used to keep
track of the items it has sent descriptions for.
Another method would be to keep track of this information when the
object changes/moves. Perhaps have a few fields of linked list of
objects in the players - one for 'changed' and one for entered field
of view. Then, when the object moves/does whatever, it checks to see
if it is in any players field of view, and if so, puts itself on
one of those lists (changed or entered field of view). Then, this
data is processed, and it would be decided if it is sent down the
line or not (determined via stacking). However, this would require
all ITEM commands need to be sent, or you once again need to keep track
someplace what items have been sent down the line (and also need to
somehow keep track of what was sent down the line but is no longer
visible.
IF anyone has good ideas on how to handle this area, I would
be interested.
Back to the player moving (S->C: ITEM 123 44 45):
When the client recieves this, it should scroll the map up one.
It now sends a map command to fill the new bottom row up:
S->C: MAP 40 50 wall 41 50 wall 42 50 wall ...
S->C: UNMAP 40 40 41 40 ...
removes the row that scrolled off. I personally don't think this
is necessary - if a row scrolls off the edge of the display, it should
be taken as an implicit unmap.
LOS is updated (IMHO, this should be done before the MAP command),
and new object that appear are sent:
S->C: ITEM 642 45 50 1 orcimage Orc chieftain
Orc wants to attack player, so it moves towards him:
S->C: ITEM 642 45 49
S->C: ITEM 642 45 48
S->C: ITEM 642 45 47
Since the item tag number is unique, each item command effectively
removes the previous location.
Problem: This requires that for each ITEM command received by the client,
the client needs to search through all the old ITEM objects it has stored
to see if an item of that tag exists someplace else.
The player decides to drop his helmet (has not moved any spaces):
C->S: MOVE 433 44 45
This is a request by the client to drop the helmet. Effectively, it is a
move out of inventory and onto the map.
S->C: ITEM 433 44 45
Server process the command. Note that the client has to search through
all the items it knows about and find the one with tag 433 and remove it.
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
S->C: TEXT <text>
Sends <text> that the client should display. Client can do whatever
it wants with the text, but should keep it intact.
Note that the TEXT sent can not have a newline in it - this is the
packet termination character. Instead, multiple TEXT commands will
need to be sent.
------------------------------------------------------------------------------
PLAY <sound> <vol>
Instructs the client to play the sound with the specified name.
<vol> is the volume of the sound. It is an integer ranging from 0 to
200. 0 would be silent (should never be sent) 100 is normal volume, and
200 is very loud (should be near max volume.) Client is free to adjust
volumes (ie, could scale them down by 50% before playing them, thus
implementing a program volume control)
It is up to the client to get sounds appropriate for it, and do any
name matching to that sound. Supporting transmissions of sounds in the
server could be done, but sound formats vary too much, plus sounds take
up a lot of space.
If running the rplayd, then it would get sounds automatically from an rplay
server that is set up. Seems pointless to recreate code that is already in
place.
------------------------------------------------------------------------------
>STAT <stat> <current> <maximum>
This tells the client that the value of the player statistic called
<stat> is <current>, with maximum the max value of that stat.
If maximum is -1, it likely means that a maximum value for that
stat is not available (experience, for example.)
How the client displays these stats is up to it.
<stat> can be any of level, exp, hp, sp, str, dex, con, wis, cha, int,
wc, ac, armor, dam, speed(*) food, weapon_sp(*)
* - These values are stored as floats, but since all other values are ints,
it is easier to transmit it as int. Thus, they will be multipled by
1000 by the server (giving 3 decimal places.) The client should reverse
this.
------------------------------------------------------------------------------
C->S: REQUEST <name> <type>
S->C: TRANSMIT <name> <type> <length>
This transmits file <name> with <type> to the client.
As of now, all of the files that get transmitted are done in text
format. But in theory, it is possible for this command to transmit
binary files.
If <length> is 0, then it is a text transmission, and END_OF_DATA
on a single line signals that is the end of the data.
<name> is the name of the data to be sent. If it has spaces, the name
should be escaped with double quotes ("), with the name itself not containing
a double quote character.
<type> for both REQUEST and TRANSMIT can be any of: XPM, BIT, or ARCH.
XPM are xpm images. All server should support this - the XPM library
will not be needed - only the data files.
BIT are the bitmaps (monochrome images). All servers must support
this data. It is up to the client whether to request a XPM or BIT file -
this will likely depend on what type of display and other options are given
to the client. Both XPM and BIT data will be in text format.
ARCH is archetype data. The full archetype is not sent - only the name
(both arch and item), and image name/animations. This must be supported.
Note that format used for ARCH TRANSMIT's is not exactly the same as used in
in archetype file. This makes it easier for the client to process, because
some information that we already know about (like the number of animations)
is supplied. Also, the animations are prefixed with an anim_image string,
so we don't need to worry about receive states.
Data will only be transmitted if the client requests it. Thus, if the
client knows it will never request XPM data (due to hardware limitations, or
perhaps a low memory client), it does not need to support receiving XPM data.
The server will send the data as fast as it gets request. Thus, the client
should only request a little at a time, otherwise the socket buffer might
overflow (if on a slow connection). What the server does in such situations
is not yet clear.
By default, the size of the socket buffer is set to 32K - this is pretty big.
Note: How the server keeps it data is up to it. It has been pointed
out to me that if the server keeps the XPM images in compressed/gzip
format, then each time a file is requested, the file will need to be
decompressed.
The data follows a set standard. Whether this is done by pulling
information out of the crossfire.pix.? files or by keeping all the
.xpm files around which the server accesses is it to it. The code
I wrote assumes things will be kept in the crossfire.pix.? format.
This note is also relevant to the bitmap data. Archetype data
is created from the archetypes already loaded in, so how that file
is stored will not affect anything.
------------------------------------------------------------------------------
>
>ERROR <type> <...>
>This command is used to indicate that a real error has occured. The
>remainder of the line is some free form text describing that error.
>What the client does with that message is up to it. This command is
>only used to indicate actual program errors which point to
>bugs/incompatibilities between it and the server such as malformed
>packets and the like. Player errors (like trying to take something
>which isn't there) are handled by normal TEXT messages.
Provision is in place for smart error messages so that the
client can act appropriately. For example, the following
are supported:
ERROR NOSUCHFILE <name> <type>
Where name and type are the same as in the REQUEST command above. In this
way, the client will know that the file is not available, and thus be able
to do something more intelligent. This should not happen - the client
should not be requesting a file unless he knows he server has it
(server uses a face or archetype name or something similar.)
ERROR FILENOTAVAIL <name> <type>
This is similar to NOSUCHFILE above, but in this case, the file exists,
but for whatever reason, can not be sent/accessed.
ERROR BADFORMAT <text>
The data command was not properly formatted. This could be caused
by several things - a string is not properly quoted, or an improper
number of arguments was given for any command (ie, REQUEST missing
name/type argument)
ERROR <text>
This is just a text based error message, that are not in any specific
category.
------------------------------------------------------------------------------
>
>QUERY <flags> <...>
>Ask the user a question with the text <...>. Some clients may want to
>pop up a requestor for this. Others may not. The answer is taken from
>the next REPLY packet sent by the client.
>
(REPLY is detailed in the C->S command section)
QUERY and REPLY are really specialty commands. While in the future
they can perhaps be extended so that when an NPC speaks, it is a known
question, right now, this can not happen.
Where QUERY and REPLY are used is for rolling up characters. For
swapping stats, or just confirming if that is what you want to select,
this is really the only way to do it. Using SAY commands would be a
real hack, and as it is, the server will know that it should do
a QUERY for rolling characters.
<flags> is the type of QUERY. Values:
#define CS_QUERY_YESNO 0x1 /* Yes/no question */
#define CS_QUERY_SINGLECHAR 0x2 /* Single character response expected */
#define CS_QUERY_HIDEINPUT 0x4 /* Hide input being entered */
Note that these flags can be OR'd together (ie, 0x5 would mean that
it is a yes/no question, but the input should be hidden)
Note - the client can pretty much ignore all of these flags, they are
just here so that the client can do more intelligent things.
------------------------------------------------------------------------------
S->C: KNOWN_SPELLS {<name>}
This is sent to inform the client of all the spells the character knows.
This allows the client to verify if certain cast commands are
legal. This is really a convenience command, but in all cases, some
verification would be required. IF the player where in the middle of
combat and tried to cast a spell, only to find out his keybinding was
mistyped, he would be very upset. Client can verify that keybindings
are correct.
Subsequent KNOWN_SPELLS after the first one denote new spells
that have been learned. Since there is no way to loose a spell
from memory, there is no need to reset the spells.
Client is free to ignore this data. When the spell is cast, the
server will verify it is correct.
Sending along spellpoint cost should be done, but this information
does vary (if SPELLPOINT_LEVEL_DEPEND is set, for example, then each
time the player gains a level, spellpoint costs change. Likewise,
items that attune or repel spells will change this, and these could
get applied quite often)
------------------------------------------------------------------------------
RANGE <range> <tag>
Tells the client that the object with <tag> is now range attack
type <range>. This is necessary because the client will not otherwise
know if a weapon causes a range attack or not. A <tag> of 0 would
mean that that range type no longer has a range attack.
<range> values: 1=bow, 3=wand, 4=rod, 5=scroll,
6=horn, 7=steal (skill).
2 is not used - this is range_magic, which the client will handle on
its own. Note that these values are teh same as the rangetype
enumeration. As that grows, sowill these.
==============================================================================
VALID COMMANDS FROM THE CLIENT TO THE SERVER
============================================
>LOGIN
This is detailed in the login section
------------------------------------------------------------------------------
>REQUEST
>TRANSMIT
>ERROR
>These three commands are valid in this direction as well with the same
>syntax and semantics.
IT is unclear what the client would ever transmit, just as it is unclear
what the server would ever request. Thus, the client can ignore REQUESTS
and not have TRANSMIT implemented.
What ERROR messages the client sends is unknown. In general, the
server should know what it is talking about, and thus the client should
never need to generate errors. And because of this, the server can not
really do much with the ERROR messages, except put them in a log file.
------------------------------------------------------------------------------
MOVE <tag> <number_of> <from_x> <from_y> <to_x> <to_y>
Where from_[xy] is where the object is, and to_[xy] is where the object
is going. This makes things easier for both the client and server to
find the object to be moved. All of these values have the same
meaning as in the ITEM command (for containers)
<number_of> is the number of objects to be moved - this allows a player to
drop 15 of 225 arrows.
Note that this is a request to the client. The server will send back
ITEM/MOVE commands if the action is possible.
This is the command that is used to move the player. A walk would
just have the to_x and to_y with a difference of 1 from the from_x and
from_y values.
To run, these values should have very large offsets (ie, if
player is at 10,10 and wants to run east, client should send
a MOVE <tag> <0> 50 10
This would keep the player moving to the right until he reaches
space 50 (which may never happen - a wall might be in the way.) To
abort the run, a new MOVE command would be sent, with new values.
The client may vary well have some default run distance it uses when
the player runs. Client could keep track of the destination it
sent, and when the player gets there, send another MOVE command with
a new destination.
Note: It was once suggested that firing objects would be handled
in this command. FIRE is now its own command. You fire stuff in
a a direction, and not at a coordinate.
---------------------------------------------------------------------------
APPLY <tag> <x> <y>
The player tries to apply the item with tag <number>, which is located
at <x> <y>.
---------------------------------------------------------------------------
FIRE <flags> <tag>
FIRE fires and object/spell.
<flags> contain direction (and possibly no direction, meaning the player
cast the spell on himself). It may be extended in the future to include
additional information (if throw is added, then setting flag to something
would indicate that the item was thrown, and not fired.)
<tag> is the item tag to be fired. <tag> will be a string to
represent spell casting
All spell casting is handled through this command. Invoking and
casting a spell are one in the same as far as this command is
concerned. IT is up to the client to handle these different (in
general, an invoked spell will be sent immediately, where casting a spell
just changes the range attack type.)
---------------------------------------------------------------------------
SAY <flags> <text>
The player says whatever the free-form text which follows on the line
is. Other players would see this by means of some TEXT message.
<flags> determines how this should be handled. Values of flag should be
as:
0x1 Text is a normal say command.
0x2 Text is actually shouted.
0x4 Text is a party say command (maybe shouldn't exist? At least not
realisticly)
------------------------------------------------------------------------------
REPLY <text>
The response to the most recent QUERY command.
Actually, the server is not likely to send another QUERY command until
the last one is answered.
------------------------------------------------------------------------------
EXAMINE <tag> <locx> <locy>
Examines object with <tag>, at <locx> <locy>. If tag is 0, then this is the
same thing as looking at a square.
All information is sent back as TEXT messages. How the client
deals with them is up to it (ie, it may try and parse them and then
do certain actions based upon the information received.)
------------------------------------------------------------------------------
COMMAND (command)
This is a simple extension. Various servers may
add commands that do not warrant extending the protocol. Right
now, there are many commands that really do not need individual
protocl requests (who, help, etc). An option in the client can
exist to pass the command directly to the server. If the
server does not understand the command, it can send the error
back as TEXT message.
Only optional commands should use the COMMAND name. A required command
should be part of the protocol. Examples of commands that might be
sent are things like who, maps, malloc, etc. There are a lot of
misc. commands which just sent back text and take no arguments.
------------------------------------------------------------------------------
C->S: SET <var> <value>
This sets a <var> to <value> on the server. Depending on display or
bandwidth, different information may not be required. This sets some
of these options:
Variables:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
STACKING (depth)
This is how many images the client plans to display per space. If
using fonts or bitmaps, then any value beyond 1 does not have any meaning
(the client probably will not be able to display them.)
For pixmaps, this can have meaning up to a reasonably high number.
The server should handle a STACKING 1 request - this
is to reduce bandwidth on clients that can not display things with
a higher stack.
How exactly the server handles other stacking requests is up to it. However,
it should never send more objects per square than the STACKING request
request level.
Things become a little more difficult with the DOUBLE_FLOOR patch
(which would show two floors.) As such, the following should
be the standard for different stacking levels:
Level What is shown
1 just the top most object
2 top object + bottom floor.
3 top object + both floors.
4+ level-2 top objects, and all floors.
This makes the STACKING systematic. Level 2 stacking probably won't
be used much. With this system, the client knows at most how many
objects it will get sent - this is quite useful, because anything more
than a couple items in 1 square become indistinguishable.
This can be changed during game play - however, how the server handles
this may vary - the server may end up resending the entire map when
the stacking changes.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
SOUND <0|1>
Whether PLAY commands should be sent from the server. If the value is
0, then client does not want PLAY commands. If 1, then play commands
should be sent.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
LOOK_DEPTH <val>
This determines how many objects should be sent for the square the player
is standing on. <val> has the same meaning as STACKING above, but should
almost always be higher.
Low values might be desired while in combat, so that if you run over a large
pile of stuff, you don't get a large delay as 30 items are sent.
------------------------------------------------------------------------------
Various thoughts are welcome. I am really worried about finding a good
way to implement the MAP and ITEM commands in an efficient manner.
Mark Wedel
master@rahul.net